package com.evil.kingdom.handler.timer;

import cn.hutool.core.lang.UUID;
import com.evil.common.core.util.StreamUtil;
import com.evil.kingdom.handler.MyWebSocketHandler;
import com.evil.kingdom.handler.SseHandler;
import com.evil.kingdom.pojo.dto.alive.*;
import com.evil.kingdom.pojo.entity.action.Battlefield;
import com.evil.kingdom.pojo.entity.action.BattlefieldSide;
import com.evil.kingdom.pojo.entity.action.Warfare;
import com.evil.kingdom.pojo.entity.base.Belong;
import com.evil.kingdom.pojo.entity.base.Side;
import com.evil.kingdom.pojo.entity.world.city.City;
import com.evil.kingdom.pojo.enums.BattlefieldTypeEnum;
import com.evil.kingdom.pojo.enums.WarfareOutcomeEnum;
import com.evil.kingdom.pojo.enums.WarfareResultEnum;
import com.evil.kingdom.service.alliance.AllianceService;
import com.evil.kingdom.service.world.city.CityService;
import com.evil.kingdom.task.timer.BaseTimerTask;
import com.evil.kingdom.task.timer.WarfareTimerTask;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.HashSet;

/**
 * 出征 处理器
 *
 * @author liyang
 * @date 2024-05-29 11:09
 */
@Slf4j
@Component
public class WarfareTimerTaskHandler extends BaseTimerTaskHandler<WarfareTimerTask> {
    public static final Logger timerTaskLogger = LoggerFactory.getLogger("KINGDOM_TIMER_TASK_LOGGER");
    public static final Logger warfareLogger = LoggerFactory.getLogger("KINGDOM_WARFARE_LOGGER");

    @Resource
    private SseHandler sseHandler;
    @Resource
    private MyWebSocketHandler myWebSocketHandler;
    @Resource
    private BattlefieldTimerTaskHandler battlefieldTimerTaskHandler;
    @Resource
    private CityService cityService;
    @Resource
    private AllianceService allianceService;

    public void buildWarfareTimerTask(Warfare warfare) {
        WarfareTimerTask task = WarfareTimerTask.build(warfare, this::removeTask, this::runCallback);
        this.addTask(task);
    }

    private void runCallback(Warfare t, WarfareTimerTask c, WarfareResultEnum r) {
        AliveMessage<AliveWarfare> warfareAliveMessage = new AliveMessage<>(new AliveWarfare(t));
        myWebSocketHandler.sendAll(warfareAliveMessage);
        sseHandler.sendWorld(warfareAliveMessage);

        // 遇到城池
        if (WarfareResultEnum.WARFARE_ACCESS == r || WarfareResultEnum.WARFARE_ATTACK == r) {
            String cityName = t.getRoute().getDestName();
            City city = cityService.findByName(cityName);
            // 攻占空城
            if (StringUtils.isBlank(city.getBelong())) {
                // 出征结果-胜利  结束出征
                c.stop();
                AliveMessage<AliveWarfareOutcome> warfareOutcomeAliveMessage = new AliveMessage<>(new AliveWarfareOutcome(WarfareOutcomeEnum.VICTORY));
                myWebSocketHandler.sendAll(warfareOutcomeAliveMessage);
                sseHandler.sendWorld(warfareOutcomeAliveMessage);
                return;
            }
            // 判断 不相同君主 && 不同盟
            if (this.conflict(city, t)) {
                // 构建战场-攻城
                Side side = this.calSide(t, city);
                this.battlefield(side, BattlefieldTypeEnum.CITY, city.getName());
                // 世界消息（TODO 偷袭不发）
                AliveMessage<AliveWarfareAttack> warfareMeetAliveMessage = new AliveMessage<>(new AliveWarfareAttack());
                myWebSocketHandler.sendAll(warfareMeetAliveMessage);
                sseHandler.sendWorld(warfareMeetAliveMessage);
            }

            // TODO 到达事件，目前使用世界信息调试
            if (WarfareResultEnum.WARFARE_ACCESS == r) {
                AliveMessage<AliveWarfareAccess> warfareAccessAliveMessage = new AliveMessage<>(new AliveWarfareAccess(t));
                myWebSocketHandler.sendAll(warfareAccessAliveMessage);
                sseHandler.sendWorld(warfareAccessAliveMessage);
            }
            return;
        }
        // 是否有冲突相遇（实际上最多一个出征同时相遇，所以这里查库操作性能还能接受）
        StreamUtil.isExistFirst(this.getList(), e -> c != e && c.meet(e) && this.conflict(t, e.getT())).ifPresent(mc -> {
            c.pause();
            mc.pause();

            Warfare mt = mc.getT();
            Side side = this.calSide(t, mt);
            // 构建战场-野外
            this.battlefield(side, BattlefieldTypeEnum.WILDERNESS, t.getLine().getName());
            // 世界消息（TODO 偷袭不发）
            AliveMessage<AliveWarfareMeet> warfareMeetAliveMessage = new AliveMessage<>(new AliveWarfareMeet());
            myWebSocketHandler.sendAll(warfareMeetAliveMessage);
            sseHandler.sendWorld(warfareMeetAliveMessage);
        });
    }

    /**
     * 构建战场
     *
     * @param side                攻防
     * @param battlefieldTypeEnum 战场类型
     * @param toponym             地名
     */
    private void battlefield(Side side, BattlefieldTypeEnum battlefieldTypeEnum, String toponym) {
        Battlefield battlefield = new Battlefield(UUID.fastUUID().toString(true), side, battlefieldTypeEnum, toponym);
        battlefieldTimerTaskHandler.buildBattlefieldTimerTask(battlefield, sideName -> {
            warfareLogger.info("warfare|battlefield|finished|{}", sideName.printInfo());
        });
    }

    /**
     * 判断是否冲突
     *
     * @param a a
     * @param b b
     * @return boolean
     */
    private boolean conflict(Belong a, Belong b) {
        // 不同君主，不同盟，则冲突
        return !a.getBelong().equals(b.getBelong()) && !allianceService.isAlliance(a, b);
    }

    private Side calSide(Warfare a, Warfare b) {
        if (a.getSpeed() >= b.getSpeed()) {
            return new BattlefieldSide(a.getMarshalName(), b.getMarshalName(), new HashSet<>(), new HashSet<>());
        }
        return new BattlefieldSide(b.getMarshalName(), a.getMarshalName(), new HashSet<>(), new HashSet<>());
    }

    private Side calSide(Warfare a, City b) {
        return new BattlefieldSide(a.getMarshalName(), b.getName(), new HashSet<>(), new HashSet<>());
    }
}
